<script setup>
import { Search, ArrowLeftBold, CircleCloseFilled } from '@element-plus/icons-vue'
import { getUserList } from '@/assets/api/user'
import { getDeptTree } from '@/assets/api/dept'
import { ElMessage } from 'element-plus'
import { getAvatars } from '@/assets/api/user'
import { match } from 'pinyin-pro'
import logo from '@/assets/image/logo.png'
import { nextTick } from 'vue'

const props = defineProps({
  modelValue: Boolean,
  // 默认选中的人员
  defaultCheckedList: {
    type: Array,
    default: () => [],
  },
  disabledMethod: Function,
})
const { defaultCheckedList } = toRefs(props)
const emit = defineEmits(['update:modelValue', 'submit'])

const searchValue = ref('')

const treeRef = ref()

watch(searchValue, (v) => {
  treeRef.value.filter(v)
})

const userTreeData = ref([])
const userListData = ref([])
const userData = ref([])
const companyName = ref('')
const loading = ref(false)

watch(
  () => props.modelValue,
  (v) => {
    if (v) {
      getUserListData()
    } else {
      close()
      setTimeout(() => {
        submitLoading.value = false
      }, 1000)
    }
  }
)

function getUserListData() {
  loading.value = true
  Promise.all([getUserList({ status: 0 }), getDeptTree()])
    .then(async (res) => {
      /**
       * @type {Array}
       */
      const userList = res[0].rows
      const deptTreeData = res[1].data
      // let ids = userList.map((item) => item.userId)
      // const data = await getAvatars(ids.join(','))
      userList.forEach((user) => {
        // user.avatar = data.data[user.userId]
        const { depts } = user
        user.label = user.nickName
        user.id = user.userId
        if (props.disabledMethod) {
          user.disabled = props.disabledMethod(user)
        }
        depts.forEach((dept) => {
          const target = findDept(deptTreeData, dept.deptId)
          if (!target.children) {
            target.children = []
          }
          target.type = 'dept'
          let catchUser = JSON.parse(JSON.stringify(user))
          catchUser.nodeId = `${dept.deptId}-${user.id}`
          // target.children.push(user)
          target.children.push(catchUser)
        })
      })
      userTreeData.value = deptTreeData
      userListData.value = userList
      userData.value = userList
      setCheckedNodes()
    })
    .finally(() => {
      loading.value = false
    })
}

function findDept(list, id) {
  for (let i = 0; i < list.length; i++) {
    if (list[i].id === id) {
      return list[i]
    }
    if (list[i].children) {
      const target = findDept(list[i].children, id)
      if (target) {
        return target
      }
    }
  }
}

// 树节点勾选人员(会有不同部门的相同人员)
const checkedList = ref([])
// 右侧选中人员
const selectList = ref([])

function selectUser(data, checked) {
  const sameUserList = findSameUserById(userTreeData.value, data.id)
  if (checked) {
    // 树勾选
    checkedList.value = [...checkedList.value, ...sameUserList]
    // 选中人员展示
    selectList.value = findUniqueUserById(checkedList.value)
  } else {
    // 树取消勾选
    checkedList.value = checkedList.value.filter((item) => item.id !== data.id)
    selectList.value = findUniqueUserById(checkedList.value)
  }

  setCheckedNodes()
}

function removeUser(data, index) {
  selectList.value.splice(index, 1)
  checkedList.value = checkedList.value.filter((item) => item.id !== data.id)
  setCheckedNodes()
}

function filterUser(value, user) {
  if (!value) return true
  if (user.label.indexOf(value) !== -1) return true
  return !!match(user.label, value)?.length
}

// 回显
watch(
  () => defaultCheckedList,
  async (v) => {
    let defaultList = JSON.parse(JSON.stringify(v.value)) || []
    let ids = defaultList.map((item) => item.id)
    const res = await getAvatars(ids.join(','))
    if (res.code === 200) {
      defaultList.forEach((user) => {
        user.userId = user.id ? user.id : user.userId
        user.avatar = res.data[user.id]
      })
      checkedList.value = defaultList
      selectList.value = defaultList
      setCheckedNodes()
    }
  },
  {
    immediate: true,
    deep: true,
  }
)

function setCheckedNodes() {
  nextTick(() => {
    if (treeRef.value) {
      treeRef.value.setCheckedNodes(checkedList.value)
    }
  })
}

// 获取树结构中相同人员
function findSameUserById(tree, id) {
  const result = []
  function recursiveFind(nodes) {
    nodes.forEach((node) => {
      if (node.id === id) {
        result.push(node)
      }
      if (node.children && node.children.length > 0) {
        recursiveFind(node.children)
      }
    })
  }
  recursiveFind(tree)
  return result
}

// 选择人员去重
function findUniqueUserById(arr) {
  const data = arr.filter((item, index, self) => {
    if (item.userId) {
      return self.findIndex((obj) => obj.id === item.id) === index
    }
  })

  return data
}

const activeTab = ref(0)
const tabList = [
  { label: '按好友', name: 0 },
  { label: '按架构', name: 1 },
  { label: '按群聊', name: 2 },
]

watch(activeTab, (v) => {
  if (v === 1) {
    userData.value = userTreeData.value
  } else {
    userData.value = userListData.value
    setCheckedNodes()
  }
})

const showStructure = ref(false)
function companyClick(data, index) {
  if (Array.isArray(data.children)) {
    userData.value = data
    showStructure.value = true
    companyName.value = data.label
    setCheckedNodes()
  }
}

function backClick() {
  userData.value = userTreeData.value
  showStructure.value = false
}

const submitLoading = ref(false)

function submit() {
  if (selectList.value.length !== 0) {
    submitLoading.value = true
    emit('submit', selectList.value)
  } else {
    ElMessage.warning('请选择人员')
  }
}

function close() {
  searchValue.value = ''
  checkedList.value = []
  selectList.value = []
  userTreeData.value = []
  userListData.value = []
  userData.value = []
  activeTab.value = 0
  showStructure.value = false
  emit('update:modelValue', false)
}
</script>

<template>
  <TaskChatDialog
    :model-value="props.modelValue"
    class="personnel-selection"
    title="人员选择"
    width="750px"
    append-to-body
    :close-on-click-modal="false"
    destroy-on-close
    bodyClassName="custom-body"
    @close="close">
    <div class="personnel-selection-body">
      <div class="user-list">
        <el-input placeholder="搜索" v-model="searchValue" clearable>
          <template #prefix>
            <el-icon size="16"><Search></Search></el-icon>
          </template>
        </el-input>
        <div class="user-list-header">
          <div v-if="showStructure" class="company-name">
            <el-icon><ArrowLeftBold @click="backClick" /></el-icon>
            <span>{{ companyName }}</span>
          </div>
          <TaskChatTab v-else v-model="activeTab" :data="tabList"></TaskChatTab>
        </div>
        <div class="user-list-container" v-loading="loading">
          <template v-if="activeTab === 1 && !showStructure">
            <div
              v-for="(item, index) in userTreeData"
              :key="index"
              class="company-item"
              @click="companyClick(item, index)">
              <SvgIcon name="personnel-company" size="34"></SvgIcon>
              <span class="personnel-label">{{ item.label }}</span>
            </div>
          </template>
          <template v-else-if="activeTab !== 1 || showStructure">
            <el-tree
              :class="{ 'icon-none': !showStructure }"
              ref="treeRef"
              :data="activeTab === 1 ? userTreeData : userData"
              :node-key="activeTab === 1 ? 'nodeId' : 'id'"
              default-expand-all
              show-checkbox
              icon=""
              @check-change="selectUser"
              :filter-node-method="filterUser">
              <template #default="{ node, data }">
                <div>
                  <div class="custom-tree-node" v-if="data.oryType === 11">
                    <SvgIcon name="personnel-dept" size="26"></SvgIcon>
                    <span class="personnel-label">{{ node.label }}</span>
                  </div>
                  <div class="custom-tree-node" v-else-if="data.oryType === 10">
                    <SvgIcon name="personnel-company" size="26"></SvgIcon>
                    <span class="personnel-label">{{ node.label }}</span>
                  </div>
                  <div class="custom-tree-node" v-else>
                    <el-avatar
                      class="organization-img"
                      :src="data.avatar || logo"
                      @error="
                        () => {
                          data.avatar = logo
                        }
                      " />
                    <span class="">{{ node.label }}</span>
                  </div>
                </div>
              </template>
            </el-tree>
          </template>
        </div>
      </div>
      <div class="selected-user">
        <span>
          已选择
          <span style="font-weight: bold">
            （{{ selectList.length }} /
            <span style="color: var(--elp-color-info)">{{ userListData.length }}</span>
            ）
          </span>
        </span>
        <div class="selected-user-list">
          <div class="selected-user-grid">
            <div class="user-item" v-for="(item, index) in selectList" :key="item.id">
              <el-avatar
                class="user-item-img"
                :src="item.avatar || logo"
                @error="
                  () => {
                    item.avatar = logo
                  }
                " />
              <span>
                {{ item.label }}
              </span>
              <el-icon class="close" size="14" @click="removeUser(item, index)"><CircleCloseFilled /></el-icon>
            </div>
          </div>
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="emit('update:modelValue', false)">取消</el-button>
      <el-button type="primary" @click="submit" :loading="submitLoading">确认</el-button>
    </template>
  </TaskChatDialog>
</template>

<style scoped lang="scss">
.personnel-selection {
  .personnel-selection-body {
    @include use-flex();
    height: 400px;
    .user-list {
      width: 274px;
      flex: 1;
      padding-right: 10px;
      border-right: var(--elp-border);
      .user-list-header {
        margin-top: 13px;
        margin-bottom: 15px;
        .company-name {
          @include use-flex(center, flex-start);
          font-weight: bold;
          font-size: 16px;
          .elp-icon {
            cursor: pointer;
            margin-right: 12px;
            color: var(--elp-text-color-secondary);
          }
        }
        .task-tab {
          @include use-flex(center, space-around);
        }
      }
      .user-list-container {
        height: 320px;
        overflow: hidden auto;
        .company-item {
          @include use-flex(center, flex-start);
          height: 46px;
          padding: 6px 8px;
          box-sizing: border-box;
          cursor: pointer;
          border-radius: var(--elp-border-radius-base);
          img {
            width: 34px;
            height: 34px;
            margin-right: 10px;
          }
          span {
            font-weight: 700;
            font-size: 14px;
          }
          &:hover {
            background-color: var(--elp-fill-color-light);
          }
        }
        :deep(.elp-tree) {
          .elp-checkbox {
            margin-right: 14px;
            .is-indeterminate {
              .elp-checkbox__inner {
                background-color: var(--elp-bg-color);
                border: var(--elp-checkbox-input-border);
              }
            }
          }
        }
        :deep(.icon-none) {
          .elp-checkbox {
            margin-left: 8px;
          }
          .elp-icon {
            display: none;
          }
        }
        .elp-tree {
          --elp-tree-node-content-height: 40px;
        }
        .custom-tree-node {
          height: 50px;
          line-height: 50px;
          position: relative;
          display: flex;
          align-items: center;
          .organization-img {
            width: 28px;
            height: 28px;
            border-radius: 50%;
            margin-right: 10px;
          }
        }
        .personnel-label {
          display: inline-block;
          margin-left: 10px;
        }
      }
      :deep(.elp-input) {
        .elp-input__wrapper {
          border-radius: 5px;
          background-color: var(--elp-color-info-light-9);
          border: 0;
          box-shadow: none;
        }
      }
    }

    .selected-user {
      width: calc(100% - 274px - 10px);
      padding-left: 10px;
      .selected-user-list {
        height: 370px;
        overflow: auto;
        .selected-user-grid {
          display: grid;
          grid-row-gap: 20px;
          grid-column-gap: 15px;
          grid-template-columns: repeat(auto-fill, 60px);
          margin-top: 24px;
          .user-item {
            position: relative;
            @include use-flex(center, center);
            flex-direction: column;
            font-size: 12px;
            color: var(--elp-text-color-secondary);
            .user-item-img {
              width: 28px;
              height: 28px;
              margin-bottom: 8px;
            }
            .close {
              position: absolute;
              top: -7px;
              right: 9px;
              cursor: pointer;
            }
          }
        }
      }
    }
  }
}
</style>
